package com.shareach.dao.mongoext;

import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.mongodb.AggregationOutput;
import com.mongodb.BasicDBObject;
import com.mongodb.CommandResult;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.MongoClient;

/**
 * mongo查询工具包
 * 
 * @author zuoshuaiok@gmail.com
 * 
 */
public class MongoGroupTool {

	private static MongoClient client;

	private static DBCollection collection = null;
	static {
		try {
			// 生产并非用此处初始化，取得是spring提供的数据源，此处用来单元测试
			client = new MongoClient("localhost", 20001);
			collection = client.getDB("ShopBase").getCollection("bizCard");
		} catch (UnknownHostException e) {
			System.err.println("-----找不到服务器");
			e.printStackTrace();
		}

	}

	public static void main(String[] args) {
		DB flow_db = client.getDB("ShopBase");
		collection = flow_db.getCollection("bizCard");
		// sample
		Where where = new Where();
		where.setKey("createTime").setLt(new Date());
		List<Where> wherelistList = new ArrayList<Where>();
		wherelistList.add(where);
		CommandResult result = GroupByResults(new BaseQuery().setSelect(GlobalStatus.COUNT.forField("count"))
				.setWhereList(new ArrayList<Where>()).setGroupBy("city"), collection);
	}

	public static CommandResult GroupByResults(BaseQuery query, DBCollection collection) {

		List<Where> whereList = query.getWhereList();
		String[] search_fields = query.getSelect().trim().split(",");
		String[] group_fields = query.getGroupBy().trim().split(",");

		DBObject matches = new BasicDBObject();
		for (Where where : whereList) {
			if (checkNullObject(where.getEq())) {
				matches.put(where.getKey(), where.getEq());
			} else if ((checkNullObject(where.getLt()) || checkNullObject(where.getLte()))
					&& (checkNullObject(where.getGt()) || checkNullObject(where.getGte()))) {
				boolean flag = checkNullObject(where.getLt());
				boolean flag_gt = checkNullObject(where.getGt());
				matches.put(where.getKey(),
						new BasicDBObject(flag ? "$lt" : "$lte", flag ? where.getLt() : where.getLte()).append(
								flag_gt ? "$gt" : "$gte", flag_gt ? where.getGt() : where.getGte()));
			} else if (checkNullObject(where.getLt()) || checkNullObject(where.getLte())) {
				boolean flag = checkNullObject(where.getLt());
				matches.put(where.getKey(),
						new BasicDBObject(flag ? "$lt" : "$lte", flag ? where.getLt() : where.getLte()));
			} else if ((checkNullObject(where.getGt())) || checkNullObject(where.getGte())) {
				boolean flag = checkNullObject(where.getGt());
				matches.put(where.getKey(),
						new BasicDBObject(flag ? "$gt" : "$gte", flag ? where.getGt() : where.getGte()));
			} else {
				System.out.println("----无合适匹配或者无匹配");
			}
		}
		DBObject match = new BasicDBObject("$match", matches);

		DBObject fields_project = new BasicDBObject();

		for (int i = 0; i < search_fields.length; i++) {
			if (checkGroupType(search_fields[i]))
				fields_project.put(search_fields[i].split(":")[1], 1);
			else {
				fields_project.put(search_fields[i], 1);
			}
		}

		for (int i = 0; i < group_fields.length; i++) {
			fields_project.put(group_fields[i], 1);
		}

		DBObject project = new BasicDBObject("$project", fields_project);

		DBObject fields_group = new BasicDBObject();
		for (int i = 0; i < group_fields.length; i++) {
			fields_group.put(group_fields[i], "$" + group_fields[i]);
		}

		DBObject groupFields = new BasicDBObject("_id", fields_group);
		for (int i = 0; i < search_fields.length; i++) {
			if (query.getGroupBy().indexOf(search_fields[i]) == -1) {

				if (checkGroupType(search_fields[i])) {
					String[] search = search_fields[i].split(":");
					if (search[0].equals(GlobalStatus.COUNT.name))
						groupFields.put(search[1], new BasicDBObject("$sum", 1));
					else {
						groupFields.put(search[1], new BasicDBObject(search[0], "$" + search[1]));
					}
				} else {
					groupFields.put(search_fields[i], new BasicDBObject("$min", ("$" + search_fields[i])));
				}
			}
		}
		DBObject group = new BasicDBObject("$group", groupFields);
		// run aggregation
		AggregationOutput output = collection.aggregate(match, project, group);
		Iterable<DBObject> list = output.results();
//		for (DBObject dbObject : list) {
//			System.out.println(dbObject.get("count") + "--" + dbObject.get("_id"));
//		}
		return output.getCommandResult();
	}

	private static boolean checkNullObject(Object param) {
		return null != param;
	}

	private static boolean checkGroupType(String param) {
		return param.indexOf(":") > 0;
	}
}
